package com.laoniu.biz;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.laoniu.dto.LoginUser;
import com.laoniu.dto.PageResponse;
import com.laoniu.dto.request.UserListDto;
import com.laoniu.dto.request.UserRequestDto;
import com.laoniu.dto.response.UserResponseDto;
import com.laoniu.entity.SecurityUser;
import com.laoniu.entity.SysUserRole;
import com.laoniu.entity.User;
import com.laoniu.service.RedisService;
import com.laoniu.service.sys.UserRoleService;
import com.laoniu.service.sys.UserService;
import com.laoniu.service.sys.LogService;
import com.laoniu.utils.JwtUtils;
import com.laoniu.utils.RedisKeyUtils;
import com.laoniu.utils.ServletUtils;
import com.laoniu.utils.SpringSecurityUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class UserBiz {

    @Value("${initpassword}")
    private String initPassword;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private PasswordEncoder bcryptPasswordEncoder;
    @Autowired
    private UserService userService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private LogService logService;
    @Autowired
    private UserRoleService userRoleService;


    /**
     * 登录用户
     * @param userDto
     * @return
     */
    public Map<String,Object> loginUser(LoginUser userDto){
        UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(userDto.getUsername(), userDto.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authToken);
        if(authenticate == null) {
            throw new RuntimeException("Login false");
        }
        SecurityUser securityUser = (SecurityUser) authenticate.getPrincipal();
        Long userId = securityUser.getId();
        String username = securityUser.getName();
        String jwt = JwtUtils.createJwt(username, userId);
        redisService.set(RedisKeyUtils.LOGIN_USER_KEY + userId, JSONObject.toJSONString(securityUser));
        Map<String, Object> result = Maps.newHashMap();
        result.put("status", 200);
        result.put("message", "操作成功");
        result.put("token", jwt);
        result.put("username", username);
        //登录日志
        logService.insertLogAddUser(securityUser,"用户登录", "{\"username\":\"" + username+ "\"}", ServletUtils.getUrl(), "用户登录","用户登录系统");
        return result;
    }

    /**
     * 添加用户
     * @param dto
     */
    public void addUser(UserRequestDto dto) {
        User user = new User();
        user.setName(dto.getName());
        user.setEmail(dto.getEmail());
        user.setSex(dto.getSex());
        user.setUsername(dto.getUsername());
        user.setMobile(dto.getMobile());
        user.setIslock(0);
        user.setPassword(bcryptPasswordEncoder.encode(initPassword));
        user.setCreatetime(LocalDateTime.now());
        user.setLastupdatetime(LocalDateTime.now());
        userService.save(user);
        saveUserRole(dto.getRoleIds(), user.getId());
    }

    /**
     * 根据id查询用户
     * @param id
     * @return
     */
    public UserResponseDto getById(Long id) {
        User user = userService.getById(id);
        if (Objects.isNull(user)){
            return null;
        }
        UserResponseDto responseDto = new UserResponseDto();
        responseDto.setId(user.getId());
        responseDto.setName(user.getName());
        responseDto.setCreatetime(user.getCreatetime());
        responseDto.setEmail(user.getEmail());
        responseDto.setIslock(user.getIslock());
        responseDto.setLastupdatetime(user.getLastupdatetime());
        responseDto.setMobile(user.getMobile());
        responseDto.setSex(user.getSex());
        responseDto.setUsername(user.getUsername());
        return responseDto;
    }

    public void updateUser(UserRequestDto dto) {
        User user = userService.getById(dto.getId());
        if (Objects.isNull(user)){
            return;
        }
        SecurityUser loginUser = SpringSecurityUtils.getUser();
        user.setName(dto.getName());
        user.setSex(dto.getSex());
        user.setUsername(dto.getUsername());
        user.setMobile(dto.getMobile());
        user.setEmail(dto.getEmail());
        user.setLastupdatetime(LocalDateTime.now());
        userService.updateById(user);
        userRoleService.deleteByUserId(dto.getId());
        //保存用户角色
        saveUserRole(dto.getRoleIds(), dto.getId());
    }

    private void saveUserRole(List<Long> roleIds, Long userId){
        SecurityUser user = SpringSecurityUtils.getUser();
        if (CollectionUtils.isNotEmpty(roleIds)){
            List<SysUserRole> userRoles = Lists.newArrayList();
            for (Long roleId : roleIds) {
                SysUserRole userRole = new SysUserRole();
                userRole.setUserId(userId);
                userRole.setRoleId(roleId);
                userRole.setOpTime(LocalDateTime.now());
                userRole.setOpId(user.getId());
                userRole.setOpName(user.getName());
                userRoles.add(userRole);
            }
            userRoleService.saveBatch(userRoles);
        }
    }

    public void deleteUser(Long id) {
        userService.removeById(id);
    }

    public PageResponse<UserResponseDto> pageList(UserListDto dto) {
        LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery(User.class);
        Page<User> page = new Page<>(dto.getPageNo(), dto.getPageSize());
        Page<User> resultPage = userService.page(page, wrapper);

        PageResponse<UserResponseDto> result = new PageResponse<UserResponseDto>();
        result.setPageNo(dto.getPageNo());
        result.setPageSize(dto.getPageSize());
        result.setTotal(resultPage.getTotal());
        if (CollectionUtils.isEmpty(resultPage.getRecords())){
            return result;
        }
        List<UserResponseDto> list = Lists.newArrayList();
        for (User record : resultPage.getRecords()) {
            UserResponseDto userResponseDto = new UserResponseDto();
            userResponseDto.setUsername(record.getUsername());
            userResponseDto.setName(record.getName());
            userResponseDto.setSex(record.getSex());
            userResponseDto.setMobile(record.getMobile());
            userResponseDto.setIslock(record.getIslock());
            userResponseDto.setEmail(record.getEmail());
            userResponseDto.setId(record.getId());
            userResponseDto.setCreatetime(record.getCreatetime());
            userResponseDto.setLastupdatetime(record.getLastupdatetime());
            list.add(userResponseDto);
        }
        result.setData(list);
        return result;
    }

    /**
     * 登出
     */
    public void logout() {
        SecurityUser user = SpringSecurityUtils.getUser();
        redisService.delKey(RedisKeyUtils.LOGIN_USER_KEY + user.getId());

    }

    /**
     * 用户角色
     * @param userId
     * @return
     */
    public List<Long> userRoles(Long userId) {
        List<SysUserRole> userRoles = userRoleService.getUserRoleByUserId(userId);
        if (CollectionUtils.isEmpty(userRoles)){
            return Lists.newArrayList();
        }
        return userRoles.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
    }
}
